import { Vector3 } from '@babylonjs/core/Maths/math.vector';
import { AbstractDragLimit } from './abstract-drag-limit';
import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
import { IDragEventData, IDragProgressEventData } from '../config/abstract-drag-config';
import { Plane } from '@babylonjs/core/Maths/math.plane';
import { Calculation } from '../../tool/calculation';


/**
 * 拖动中的回调函数
 * @param target 对象
 * @param manual 是否手动
 */
interface IProgressCallback {
    (target: TransformNode, manual: boolean): void
}

/**
 * 约束在给定法线的平面上拖动
 * @param normal 平面法线
 */
class DragNormalLimit extends AbstractDragLimit {

    private _normal = new Vector3();
    private _plane = new Plane(0, 0, 0, 0);
    private _tmpOri = new Vector3();

    constructor(normal: Vector3) {
        super();
        this.setInformation(normal);
    }

    public get limitType(): string {
        return 'NormalLimit';
    }

    public setInformation(normal: Vector3): void {
        this._normal.copyFrom(normal);
    }

    public update(target: TransformNode): void {
        if (this.updateCall) this.updateCall(target, false);
    }

    public extract() {
    }

    /**
     * 拖动中的回调函数
     * @param func (target:目标;manual:手动触发):void
     */
    public set onUpdate(func: IProgressCallback) {
        this.updateCall = func;
    }

    public setStart(target: TransformNode, eventData: IDragEventData): void {
        super.setStart(target, eventData);
        const wp = target.absolutePosition;
        this.startOffset.copyFrom(this.currentPosition).subtractInPlace(wp);

        Calculation.setPlaneFromPositionAndNormal(this.currentPosition, this._normal, this._plane);
    }

    public setProgress(target: TransformNode, eventData: IDragProgressEventData): void {
        super.setProgress(target, eventData);
        const camera = this.getActiveCamera(target.getScene());
        if (!camera) return;
        this._tmpOri.copyFrom(camera.globalPosition);
        this.currentPosition.projectOnPlaneToRef(this._plane, this._tmpOri, this.currentPosition);
        if (this.updateCall) this.updateCall(target, true, eventData);
    }

}


export { DragNormalLimit };